package com.northpool.operator.http.covert;

import cn.hutool.core.util.StrUtil;
import com.northpool.operator.annotation.InputParam;
import com.northpool.operator.annotation.InputParams;
import com.northpool.operator.annotation.OperatorInfo;
import com.northpool.operator.common.algorithm.OperatorTestBuild;
import com.northpool.operator.common.algorithm.TestParamBuilder;
import com.northpool.operator.common.minio.MinIOUtil;
import com.northpool.operator.common.util.XmlParser;
import com.northpool.operator.http.bean.HttpOperatorBean;
import com.northpool.operator.http.bean.LogApiBean;
import com.northpool.operator.http.bean.ProgressApi;
import com.northpool.operator.http.bean.ResultApiBean;
import com.northpool.operator.http.bean.StartApiBean;
import com.northpool.operator.http.bean.StatusApiBean;
import com.northpool.operator.param.ParamTool;
import com.northpool.operator.type.TypeEnum;
import com.northpool.operator.utils.StpOperatorHelper;
import io.minio.Result;
import io.minio.messages.Item;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;

@OperatorInfo(
        ref = "XMLAddrChangeOperator",
        name = "HTTP算子服务地址变更",
        description = "扫描对象存储中的HTTP算子描述XML文件，修改其中的URL地址"
)
public class XMLAddrChangeOperator extends StpOperatorHelper {

    @InputParams({
            @InputParam(ref = "path", name = "minio中对象路径", desc = "minio中对象路径, 如: apps/supermap/", required = true),
            @InputParam(ref = "minioEndpoint", name = "对象存储地址", desc = "http://ip:port", required = true),
            @InputParam(ref = "bucket", name = "桶名称", desc = "桶名称, 如: stp-minio", required = true),
            @InputParam(ref = "accessKey", name = "minio令牌", desc = "minio令牌", type = TypeEnum.STRING, required = true),
            @InputParam(ref = "secretKey", name = "minio密钥", desc = "minio密钥", type = TypeEnum.STRING, required = true),
            @InputParam(ref = "sourceUrl", name = "原始地址", desc = "原始地址", type = TypeEnum.STRING, required = true),
            @InputParam(ref = "targetUrl", name = "修改后地址", desc = "修改后地址", type = TypeEnum.STRING, required = true),
    })
    public XMLAddrChangeOperator() {

    }

    public static void main(String[] args) throws Exception {
        OperatorTestBuild.execute(XMLAddrChangeOperator.class, TestParamBuilder.aBuilder()
                .param("path", "apps/supermap/")
                .param("minioEndpoint", "http://northpool.work:9000")
                .param("bucket", "stp-minio")
                .param("accessKey", "northpool")
                .param("secretKey", "piesat@123")
                .param("sourceUrl", "http://10.80.1.176:9033")
                .param("targetUrl", "http://192.168.185.14:9033")
                .build());
    }

    @Override
    public void execute(ParamTool paramTool) throws Exception {
        String bucket = paramTool.getStr("bucket");
        String path = paramTool.getStr("path");
        String minioEndpoint = paramTool.getStr("minioEndpoint");
        String accessKey = paramTool.getStr("accessKey");
        String secretKey = paramTool.getStr("secretKey");
        String sourceUrl = paramTool.getStr("sourceUrl");
        String targetUrl = paramTool.getStr("targetUrl");

        if (StrUtil.isBlank(sourceUrl) || !sourceUrl.startsWith("http")) {
            throw new RuntimeException("参数: sourceUrl 不能为空, 且开头必需为http或https");
        } else if (StrUtil.isBlank(targetUrl) || !sourceUrl.startsWith("http")) {
            throw new RuntimeException("参数: targetUrl 不能为空, 且开头必需为http或https");
        }

        MinIOUtil minioUtil = new MinIOUtil(minioEndpoint, accessKey, secretKey);
        try {
            processDirItem(minioUtil, bucket, path, sourceUrl, targetUrl);
        } catch (Exception ex) {
            error("处理失败" + ex.getMessage());
            failedExit();
        }
    }

    private void processDirItem(MinIOUtil minioUtil, String bucket, String path, String sourceUrl, String targetUrl) throws Exception {
        Iterable<Result<Item>> results = minioUtil.listObjects(bucket, path);
        for (Result<Item> result : results) {
            Item item = result.get();
            boolean dir = item.isDir();
            if (dir) {
                processDirItem(minioUtil, bucket, item.objectName(), sourceUrl, targetUrl);
            } else {
                try {
                    processFileItem(minioUtil, bucket, item.objectName(), sourceUrl, targetUrl);
                } catch (Exception ex) {
                    log("地址变更处理失败：" + item.objectName());
                }

            }
        }
    }

    private void processFileItem(MinIOUtil minioUtil, String bucket, String objectName, String sourceUrl, String targetUrl) throws Exception {
        if (!objectName.endsWith(".xml") || objectName.endsWith("STP_META.xml")) {
            return;
        }
        InputStream inputStream = minioUtil.getObject(bucket, objectName);
        HttpOperatorBean httpOperatorBean = XmlParser.parserByInputStream(inputStream, HttpOperatorBean.class);
        StartApiBean startApi = httpOperatorBean.getStartApi();
        StatusApiBean statusApi = httpOperatorBean.getStatusApi();
        ProgressApi progressApi = httpOperatorBean.getProgressApi();
        LogApiBean logApi = httpOperatorBean.getLogApi();
        ResultApiBean resultApi = httpOperatorBean.getResultApi();

        startApi.setUrl(startApi.getUrl().replace(sourceUrl, targetUrl));
        if (statusApi != null) {
            statusApi.setUrl(statusApi.getUrl().replace(sourceUrl, targetUrl));
        }
        if (progressApi != null) {
            progressApi.setUrl(progressApi.getUrl().replace(sourceUrl, targetUrl));
        }
        if (logApi != null) {
            logApi.setUrl(logApi.getUrl().replace(sourceUrl, targetUrl));
        }
        if (resultApi != null) {
            resultApi.setUrl(resultApi.getUrl().replace(sourceUrl, targetUrl));
        }

        String targetXml = XmlParser.convertToXml(httpOperatorBean);

        // 删除原有的xml文件
        minioUtil.removeObject(bucket, objectName);

        // 新增格式化后的xml文件
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(targetXml.getBytes(StandardCharsets.UTF_8));
        minioUtil.putObject(bucket, objectName, byteArrayInputStream, "text/xml; charset=utf-8");
        log("处理完成：" + objectName);
    }


}
